use std::collections::HashSet;
use std::fmt;

use crate::{DomNode, NodeType};

/// HTML验证错误类型
#[derive(Debug)]
pub enum ValidationError {
    /// 元素嵌套不当，例如在<span>中放置<div>
    InvalidNesting(String),
    /// 无效的子元素，例如在<ul>中放非<li>元素
    InvalidChild(String),
    /// 缺少必需的属性，例如<img>缺少alt
    MissingRequiredAttribute(String),
    /// 其他验证错误
    Other(String),
}

impl fmt::Display for ValidationError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ValidationError::InvalidNesting(msg) => write!(f, "无效的元素嵌套: {}", msg),
            ValidationError::InvalidChild(msg) => write!(f, "无效的子元素: {}", msg),
            ValidationError::MissingRequiredAttribute(msg) => write!(f, "缺少必需的属性: {}", msg),
            ValidationError::Other(msg) => write!(f, "验证错误: {}", msg),
        }
    }
}

impl std::error::Error for ValidationError {}

/// HTML验证器
#[derive(Debug)]
pub struct HtmlValidator {
    /// 内联元素集合
    inline_elements: HashSet<String>,
    /// 块级元素集合
    block_elements: HashSet<String>,
    /// 必需属性映射，键为元素名，值为必需属性集合
    required_attributes: std::collections::HashMap<String, HashSet<String>>,
    /// 特殊元素有效子元素映射
    valid_children: std::collections::HashMap<String, HashSet<String>>,
}

impl HtmlValidator {
    /// 创建新的HTML验证器
    pub fn new() -> Self {
        let mut validator = Self {
            inline_elements: HashSet::new(),
            block_elements: HashSet::new(),
            required_attributes: std::collections::HashMap::new(),
            valid_children: std::collections::HashMap::new(),
        };
        validator.init();
        validator
    }

    /// 初始化验证器
    fn init(&mut self) {
        // 添加常见的内联元素
        for &el in &[
            "a", "abbr", "b", "bdi", "bdo", "br", "button", "cite", "code", "data", "dfn", "em",
            "i", "img", "input", "kbd", "label", "mark", "q", "s", "samp", "small", "span",
            "strong", "sub", "sup", "time", "u", "var",
        ] {
            self.inline_elements.insert(el.to_string());
        }

        // 添加常见的块级元素
        for &el in &[
            "address",
            "article",
            "aside",
            "blockquote",
            "details",
            "dialog",
            "div", // 确保div被明确标记为块级元素
            "dl",
            "fieldset",
            "figcaption",
            "figure",
            "footer",
            "form",
            "h1",
            "h2",
            "h3",
            "h4",
            "h5",
            "h6",
            "header",
            "hgroup",
            "hr",
            "main",
            "nav",
            "ol",
            "p",
            "pre",
            "section",
            "table",
            "ul",
        ] {
            self.block_elements.insert(el.to_string());
        }

        // 添加必需属性
        let mut img_attrs = HashSet::new();
        img_attrs.insert("alt".to_string());
        self.required_attributes
            .insert("img".to_string(), img_attrs);

        // 添加特殊元素有效子元素
        let mut ul_children = HashSet::new();
        ul_children.insert("li".to_string());
        self.valid_children.insert("ul".to_string(), ul_children);

        let mut ol_children = HashSet::new();
        ol_children.insert("li".to_string());
        self.valid_children.insert("ol".to_string(), ol_children);
    }

    /// 添加内联元素
    pub fn add_inline_element(&mut self, element: &str) {
        self.inline_elements.insert(element.to_string());
    }

    /// 添加块级元素
    pub fn add_block_element(&mut self, element: &str) {
        self.block_elements.insert(element.to_string());
    }

    /// 检查元素是否为内联元素
    pub fn is_inline_element(&self, tag_name: &str) -> bool {
        self.inline_elements.contains(tag_name)
    }

    /// 检查元素是否为块级元素
    pub fn is_block_element(&self, tag_name: &str) -> bool {
        self.block_elements.contains(tag_name)
    }

    /// 验证DOM树
    pub fn validate(&self, node: &DomNode) -> Result<(), ValidationError> {
        // 递归验证所有节点
        self.validate_node(node)?;
        Ok(())
    }

    /// 验证单个节点
    fn validate_node(&self, node: &DomNode) -> Result<(), ValidationError> {
        if let NodeType::Element(tag_name) = &node.node_type {
            // 优先检查form嵌套 - 这是一种特殊情况
            if tag_name.as_ref() == "form" {
                // 递归检查form中是否嵌套了form
                self.check_for_nested_forms(node)?;
            }

            // 验证必需属性
            self.validate_required_attributes(tag_name.as_ref(), &node.attributes)?;

            // 验证有效子元素
            self.validate_valid_children(tag_name.as_ref(), &node.children)?;

            // 验证元素嵌套
            self.validate_nesting(tag_name.as_ref(), &node.children)?;

            // 特殊元素验证
            self.validate_special_elements(tag_name.as_ref(), node)?;

            // 验证结构完整性
            self.validate_structure_integrity(tag_name.as_ref(), node)?;
        }

        // 递归验证子节点
        for child in &node.children {
            self.validate_node(child)?;
        }

        Ok(())
    }

    /// 专门用于检测嵌套form的方法
    fn check_for_nested_forms(&self, node: &DomNode) -> Result<(), ValidationError> {
        // 遍历所有子元素，查找form标签
        for child in &node.children {
            if let NodeType::Element(child_tag) = &child.node_type {
                if child_tag.as_ref() == "form" {
                    return Err(ValidationError::InvalidNesting(
                        "form标签不能嵌套form标签".to_string(),
                    ));
                }
            }

            // 递归检查深层嵌套
            self.find_nested_form(child)?;
        }

        Ok(())
    }

    /// 递归查找嵌套的form标签
    fn find_nested_form(&self, node: &DomNode) -> Result<(), ValidationError> {
        if let NodeType::Element(tag_name) = &node.node_type {
            if tag_name.as_ref() == "form" {
                return Err(ValidationError::InvalidNesting(
                    "form标签不能嵌套form标签".to_string(),
                ));
            }
        }

        // 递归检查所有子节点
        for child in &node.children {
            self.find_nested_form(child)?;
        }

        Ok(())
    }

    /// 验证必需属性
    fn validate_required_attributes(
        &self,
        tag_name: &str,
        attributes: &[crate::Attribute],
    ) -> Result<(), ValidationError> {
        if let Some(required_attrs) = self.required_attributes.get(tag_name) {
            let attr_names: HashSet<String> =
                attributes.iter().map(|attr| attr.name.clone()).collect();

            for required in required_attrs {
                if !attr_names.contains(required) {
                    return Err(ValidationError::MissingRequiredAttribute(format!(
                        "元素<{}>缺少必需的属性'{}'",
                        tag_name, required
                    )));
                }
            }
        }

        Ok(())
    }

    /// 验证有效子元素
    fn validate_valid_children(
        &self,
        tag_name: &str,
        children: &[DomNode],
    ) -> Result<(), ValidationError> {
        if let Some(valid_children) = self.valid_children.get(tag_name) {
            for child in children {
                if let NodeType::Element(child_tag) = &child.node_type {
                    if !valid_children.contains(child_tag.as_ref()) {
                        return Err(ValidationError::InvalidChild(format!(
                            "元素<{}>不允许包含<{}>子元素",
                            tag_name, child_tag
                        )));
                    }
                }
            }
        }

        Ok(())
    }

    /// 验证元素嵌套
    fn validate_nesting(
        &self,
        tag_name: &str,
        children: &[DomNode],
    ) -> Result<(), ValidationError> {
        // 如果是内联元素，不应该包含块级元素
        if self.inline_elements.contains(tag_name) {
            for child in children {
                if let NodeType::Element(child_tag) = &child.node_type {
                    // 检查直接子元素
                    if self.block_elements.contains(child_tag.as_ref()) {
                        return Err(ValidationError::InvalidNesting(format!(
                            "内联元素<{}>不应包含块级元素<{}>",
                            tag_name, child_tag
                        )));
                    }
                }
            }
        }

        Ok(())
    }

    /// 改进特殊元素验证
    fn validate_special_elements(
        &self,
        tag_name: &str,
        node: &DomNode,
    ) -> Result<(), ValidationError> {
        // a标签不能嵌套a标签
        if tag_name == "a" {
            // 深度优先搜索查找嵌套的a标签
            for child in &node.children {
                if let NodeType::Element(child_tag) = &child.node_type {
                    if child_tag.as_ref() == "a" {
                        return Err(ValidationError::InvalidNesting(
                            "a标签不能嵌套a标签".to_string(),
                        ));
                    }
                }

                // 递归检查
                if let NodeType::Element(_) = &child.node_type {
                    self.validate_special_elements("a", child)?;
                }
            }
        }

        // 自闭合元素不应该有子元素
        let void_elements = [
            "img", "br", "hr", "input", "link", "meta", "area", "base", "col", "embed", "source",
            "track", "wbr",
        ];

        if void_elements.contains(&tag_name) && !node.children.is_empty() {
            return Err(ValidationError::InvalidChild(format!(
                "自闭合元素<{}>不应有子元素",
                tag_name
            )));
        }

        Ok(())
    }

    /// 验证结构完整性
    fn validate_structure_integrity(
        &self,
        tag_name: &str,
        node: &DomNode,
    ) -> Result<(), ValidationError> {
        // 结构完整性验证
        match tag_name {
            "div" => {
                // 检查div中的p标签是否正确嵌套
                // 简化检测，实际应该更复杂
            }
            "table" => {
                // 检查表格结构是否合理
            }
            _ => {}
        }

        Ok(())
    }
}

// 添加正确的Default实现
impl Default for HtmlValidator {
    fn default() -> Self {
        Self::new()
    }
}
